// Fill out your copyright notice in the Description page of Project Settings.

#include "Characters\MyCharacter.h"
#include "GameFramework\SpringArmComponent.h"
#include "Camera\CameraComponent.h"
#include "GameFramework\CharacterMovementComponent.h"
#include "GroomComponent.h"
#include "Items\Item.h"
#include "Items\Weapons\Weapon.h"
#include "Items\Soul.h"
#include "Items\Treasure.h"
#include "HUD\MyHUD.h"
#include "HUD\MyOverlay.h"
#include "Components\AttributeComponent.h"

AMyCharacter::AMyCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;
	bUseControllerRotationPitch = false;

	GetMesh()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
	GetMesh()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
	GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
	GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldDynamic, ECollisionResponse::ECR_Overlap);
	GetMesh()->SetGenerateOverlapEvents(true);

	GetCharacterMovement()->bOrientRotationToMovement = true;
	GetCharacterMovement()->RotationRate = FRotator(0.f,380.f,0.f);

	SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	SpringArm->SetupAttachment(GetRootComponent());
	SpringArm->TargetArmLength = 300.f;

	ViewCamera = CreateDefaultSubobject<UCameraComponent>(FName("ViewCamera"));
	ViewCamera->SetupAttachment(SpringArm);

	Hair = CreateDefaultSubobject<UGroomComponent>(FName("Hair"));
	Hair->SetupAttachment(GetMesh());
	Hair->AttachmentName = FString("head");

	Eyebrows = CreateDefaultSubobject<UGroomComponent>(FName("Eyebrows"));
	Eyebrows->SetupAttachment(GetMesh());
	Eyebrows->AttachmentName = FString("head");
}

void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	Tags.Add(FName("EngageableTarget"));

	InitializeMyOverlay();
}

void AMyCharacter::InitializeMyOverlay()
{
	APlayerController* PlayContrller = Cast<APlayerController>(GetController());
	if (PlayContrller)
	{
		AMyHUD* MyHUD = Cast<AMyHUD>(PlayContrller->GetHUD());
		if (MyHUD)
		{
			MyOverlay = MyHUD->GetMyOverlay();
			if (MyOverlay)
			{
				MyOverlay->SetHealBarPercent(Attributes->GetHealthPercent());
				MyOverlay->SetStaminaPercent(1.f);
				MyOverlay->SetGold(0);
				MyOverlay->SetSouls(0);
			}
		}

	}
}


void AMyCharacter::MoveForward(float Value)
{
	if (ActionState != EActionState::EAS_Unoccupied) return;
	
	if ((Controller != nullptr) && (Value != 0))
	{
		const FRotator ControlRotation = GetControlRotation();
		const FRotator YawRotation(0.f, ControlRotation.Yaw, 0.f);

		FVector Direction =  FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
		AddMovementInput(Direction, Value);
	}
}

void AMyCharacter::MoveRight(float Value)
{
	if (ActionState != EActionState::EAS_Unoccupied) return;
	if ((Controller != nullptr) && (Value != 0))
	{
		const FRotator ControlRotation = GetControlRotation();
		const FRotator YawRotation(0.f, ControlRotation.Yaw, 0.f);

		FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
		AddMovementInput(Direction, Value);
	}
}

void AMyCharacter::Turn(float Value)
{
	if ((Controller != nullptr) && (Value != 0))
	{
		AddControllerYawInput(Value);
	}
}

void AMyCharacter::Lookup(float Value)
{
	if ((Controller != nullptr) && (Value != 0))
	{
		AddControllerPitchInput(Value);
	}
}

void AMyCharacter::EKeyPressed()
{
	AWeapon* Weapon = Cast<AWeapon>(OverlappingItem);
	if (OverlappingItem)
	{
		if (EquippedWeapon)
			EquippedWeapon->Destroy();

		OverlappingItem->PickItem(this->GetMesh(),FName("RightHandSocket"),this,this);
		CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
		OverlappingItem = nullptr;
		EquippedWeapon = Weapon;
		
	}
	else
	{
		if (CanDisarm())
		{
			PlayEquipMontage(FName("Unequip"));
			CharacterState = ECharacterState::ECS_Unequipped;
			ActionState = EActionState::EAS_EquippingWeapon;
		}
		else if (CanArm())
		{
			
			PlayEquipMontage(FName("Equip"));
			CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
			ActionState = EActionState::EAS_EquippingWeapon;
		}	
		
	}
	
}

void AMyCharacter::Attack()
{
	Super::Attack();
	if (CanAttack())
	{
		PlayAttackMontage();
		ActionState = EActionState::EAS_Attacking;
	}
}

void AMyCharacter::Jump()
{
	if (ActionState == EActionState::EAS_Unoccupied)
	{
		Super::Jump();
	}
}

void AMyCharacter::Dodge()
{
	if (ActionState != EActionState::EAS_Unoccupied &&
		Attributes && Attributes->GetStamina() > 0
		) return;
	if(Attributes->CheckEnoughStamina(14.f))
	{
		ActionState = EActionState::EAS_Dodge;
		PlayDodgeMontage();
		Attributes->UseStamina(14.f);
		MyOverlay->SetStaminaPercent(Attributes->GetStaminaPercent());
	}
}

void AMyCharacter::PlayEquipMontage(FName Section)
{
	if(EquipMontage)
		PlayMontageSection(EquipMontage, Section);
}

void AMyCharacter::PlayDodgeMontage()
{
	if (DodgeMontage)
		PlayMontageSection(DodgeMontage, FName("Default"));
}

bool AMyCharacter::CanAttack()
{
	return ActionState == EActionState::EAS_Unoccupied && CharacterState!=ECharacterState::ECS_Unequipped;
}


bool AMyCharacter::CanDisarm()
{
	return CharacterState != ECharacterState::ECS_Unequipped &&
		ActionState == EActionState::EAS_Unoccupied ;
}

bool AMyCharacter::CanArm()
{
	return CharacterState == ECharacterState::ECS_Unequipped &&
		ActionState == EActionState::EAS_Unoccupied && EquippedWeapon;
}

void AMyCharacter::Die_Implementation()
{
	Super::Die_Implementation();
	ActionState = EActionState::EAS_Death;
	GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

void AMyCharacter::AttachWeaponToBack()
{
	if (EquippedWeapon)
	{
		EquippedWeapon->AttachMeshToSocket(GetMesh(), FName("SpineSocket"));
	}
}

void AMyCharacter::AttachWeaponToHand()
{
	if (EquippedWeapon)
	{
		EquippedWeapon->AttachMeshToSocket(GetMesh(), FName("RightHandSocket"));
	}
}


void AMyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (ActionState == EActionState::EAS_Unoccupied&& Attributes&&MyOverlay) 
	{
		Attributes->RegenStamina(DeltaTime);
		MyOverlay->SetStaminaPercent(Attributes->GetStaminaPercent());
	}
}

void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis(FName("MoveForward"),this, &AMyCharacter::MoveForward);
	PlayerInputComponent->BindAxis(FName("MoveRight"), this, &AMyCharacter::MoveRight);
	PlayerInputComponent->BindAxis(FName("Turn"), this, &AMyCharacter::Turn);
	PlayerInputComponent->BindAxis(FName("Lookup"), this, &AMyCharacter::Lookup);

	PlayerInputComponent->BindAction(FName("Jump"), IE_Pressed, this, &AMyCharacter::Jump);
	PlayerInputComponent->BindAction(FName("Equip"), IE_Pressed, this, &AMyCharacter::EKeyPressed);
	PlayerInputComponent->BindAction(FName("Attack"), IE_Pressed, this, &AMyCharacter::Attack);
	PlayerInputComponent->BindAction(FName("Dodge"), IE_Pressed, this, &AMyCharacter::Dodge);
}

void AMyCharacter::GetHit_Implementation(const FVector& ImpactPoint, AActor* Hitter)
{
	Super::GetHit_Implementation(ImpactPoint, Hitter);
	if (ActionState != EActionState::EAS_Death)
	{
		ActionState = EActionState::EAS_HitReaction;
		SetWeaponBoxCollisionEnabled(ECollisionEnabled::NoCollision);
	}
}

float AMyCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	HandleDamage(DamageAmount);
	if (MyOverlay)
		MyOverlay->SetHealBarPercent(Attributes->GetHealthPercent());
	return DamageAmount;
}

void AMyCharacter::SetOverlappingItem(AItem* Item)
{
	OverlappingItem = Item;
}

void AMyCharacter::AddSoul(ASoul* Item)
{
	if (Attributes && MyOverlay)
	{
		Attributes->AddSouls(Item->GetSouls());
		MyOverlay->SetSouls(Attributes->GetSouls());
	}

}

void AMyCharacter::AddGold(ATreasure* Treasure)
{
	if (Attributes && MyOverlay)
	{
		Attributes->AddGold(Treasure->GetGold());
		MyOverlay->SetGold(Attributes->GetGold());
	}
}



